#include "GameSetting.h"
#include "YHFileManager.h"
#include "DesCrypter.h"
#include "tinyxml.h"
CRoleSetting::CRoleSetting()
{
	m_roleName = "";
	m_isMusicOn = true;
	m_isMusicEffectOn = true;
}

CRoleSetting::~CRoleSetting()
{
	
}



CUserSetting::CUserSetting()
{
	m_userName = "NoName";
	m_isRememberPassword = true;
	m_passWord = "";
}

CUserSetting::~CUserSetting()
{
	for (int i = 0; i < m_roles.size(); i ++)
	{
		delete m_roles[i];
	}
}

bool CUserSetting::initSettings(string pathName)
{
	bool ret = false;
	m_pathName = pathName;
    
	string fileName = m_pathName + "/" + FILE_USER_SETTING;
	string fileRoleName = m_pathName + "/" + FILE_ROLE_SETTING;
    bool isDirectory = false;
	if (!YHFileManger::sharedInstance()->fileExistsAtPath(fileName.c_str(), &isDirectory))	//如果不存在则需要进行创建
	{
		YHFileManger::sharedInstance()->createDirectory(m_pathName.c_str(),"");
		TiXmlDocument* doc = new TiXmlDocument();
		TiXmlElement* root = new TiXmlElement(KEY_ROOT);
		doc->LinkEndChild(root);
		TiXmlElement* userName = new TiXmlElement(KEY_USER_NAME);
		root->LinkEndChild(userName);
		TiXmlText* userNameValue = new TiXmlText(m_userName.c_str());
		userName->LinkEndChild(userNameValue);
		
		TiXmlElement* isRememberPassWord = new TiXmlElement(KEY_IS_REMEMBER_PASSWORD);
		root->LinkEndChild(isRememberPassWord);
		TiXmlText* isRememberPassWordValue = new TiXmlText(m_isRememberPassword ? VALUE_BOOL_TRUE : VALUE_BOOL_FALSE);
		isRememberPassWord->LinkEndChild(isRememberPassWordValue);
		TiXmlElement* passWord = new TiXmlElement(KEY_PASSWORD);
		root->LinkEndChild(passWord);
        
		TiXmlElement* roles = new TiXmlElement(KEY_ROLES);
		root->LinkEndChild(roles);
        
		//进行加密
        if (true == VALUE_BOOL_IS_FILE_ENCRYPTED)
        {
            TiXmlPrinter printer ;
            doc->Accept(&printer);
            const char* content = printer.CStr();
            DesEncrypt(content, (char*)KEY_DES_KEY , fileName.c_str());
            delete doc;
        }
        else
        {
            doc->SaveFile(fileName.c_str());
            delete doc;
        }
		
	}
    
	if (YHFileManger::sharedInstance()->fileExistsAtPath(fileName.c_str(), &isDirectory))//读取
	{
        TiXmlDocument* doc = new TiXmlDocument();
        if (true == VALUE_BOOL_IS_FILE_ENCRYPTED) {
            char* content = NULL;
            DesDecrypt(fileName.c_str(),  (char*)KEY_DES_KEY, content);
           
            const char* pRet = doc->Parse(content);
            if (! pRet)
            {
                delete doc;
                ret = false;
            }
            else
            {
                ret = true;
            }
        }
		else {
            ret = doc->LoadFile(fileName.c_str());
            if (!ret) {
                delete doc;
            }
        }
		
        if (true == ret)
		{
			TiXmlElement* root =  doc->RootElement();
            
			TiXmlElement* userName = root->FirstChildElement(KEY_USER_NAME);
			TiXmlText* userNameValue = (userName->FirstChild())->ToText();
			m_userName = userNameValue->Value();
            
			TiXmlElement* isRememberPassword = root->FirstChildElement(KEY_IS_REMEMBER_PASSWORD);
			TiXmlText* isRememberPasswordValue =(isRememberPassword->FirstChild())->ToText();
			if (0 == strcmp(isRememberPasswordValue->Value(), VALUE_BOOL_TRUE)) //如果有记住密码，则取出密码
			{
				TiXmlElement* passWord = root->FirstChildElement(KEY_PASSWORD);
				TiXmlNode* child = passWord->FirstChild();
				if (child != NULL) //假如密码存在则取出
				{
					TiXmlText* passWordValue = child->ToText();
					m_passWord = passWordValue->Value();
				}
			}
			else
			{
				//do nothing
			}
            
			TiXmlElement* roles = root->FirstChildElement(KEY_ROLES);
            
			for (TiXmlElement* roleItem = roles->FirstChildElement(); roleItem != NULL; roleItem = roleItem->NextSiblingElement())
			{
				CRoleSetting* roleSetting = new CRoleSetting();
                
				//角色名字
				TiXmlElement* roleName= roleItem->FirstChildElement(KEY_ROLE_NAME);
				TiXmlText* roleNameValue = (roleName->FirstChild())->ToText();
				roleSetting->setRoleName(roleNameValue->Value());
				//是否开启音乐
				TiXmlElement* isMusicOn = roleItem->FirstChildElement(KEY_IS_MUSIC_ON);
				TiXmlText* isMusicOnValue =(isMusicOn->FirstChild())->ToText();
				if (0 == strcmp(isMusicOnValue->Value(), VALUE_BOOL_TRUE)) //开启
				{
					roleSetting->setIsMusicOn(true);
				}
				else
				{
					roleSetting->setIsMusicOn(false);
				}
				//是否开启音效
				TiXmlElement* isMusicEffectOn = roleItem->FirstChildElement(KEY_IS_MUSIC_EFFECT_ON);
				TiXmlText* isMusicEffectOnValue =(isMusicEffectOn->FirstChild())->ToText();
				if (0 == strcmp(isMusicEffectOnValue->Value(), VALUE_BOOL_TRUE)) //开启
				{
					roleSetting->setIsMusicEffectOn(true);
				}
				else
				{
					roleSetting->setIsMusicEffectOn(false);
				}
				m_roles.push_back(roleSetting);
			}
			delete doc;
			ret = true;
		}
	}
	return ret;
}

bool CUserSetting::saveSettings()
{
	string fileName = m_pathName + "/" + FILE_USER_SETTING;
    bool bIsDirectory = false;
    
	if (!YHFileManger::sharedInstance()->fileExistsAtPath(fileName.c_str(), &bIsDirectory))//如果不存在则需要进行创建
	{
		YHFileManger::sharedInstance()->createDirectory(m_pathName.c_str(),"");
		TiXmlDocument* doc = new TiXmlDocument();
		TiXmlElement* root = new TiXmlElement(KEY_ROOT);
		doc->LinkEndChild(root);
		TiXmlElement* userName = new TiXmlElement(KEY_USER_NAME);
		root->LinkEndChild(userName);
		TiXmlText* userNameValue = new TiXmlText(m_userName.c_str());
		userName->LinkEndChild(userNameValue);
        
		TiXmlElement* isRememberPassWord = new TiXmlElement(KEY_IS_REMEMBER_PASSWORD);
		root->LinkEndChild(isRememberPassWord);
		TiXmlText* isRememberPassWordValue = new TiXmlText(m_isRememberPassword ? VALUE_BOOL_TRUE : VALUE_BOOL_FALSE);
		isRememberPassWord->LinkEndChild(isRememberPassWordValue);
		TiXmlElement* passWord = new TiXmlElement(KEY_PASSWORD);
		root->LinkEndChild(passWord);
		if (m_isRememberPassword)
		{
			TiXmlText* passWordValue = new TiXmlText(m_passWord.c_str());
			passWord->LinkEndChild(passWordValue);
		}
        
		TiXmlElement* roles = new TiXmlElement(KEY_ROLES);
		root->LinkEndChild(roles);
		
		//进行加密
        if (true == VALUE_BOOL_IS_FILE_ENCRYPTED)
        {
            TiXmlPrinter printer ;
            doc->Accept(&printer);
            const char* content = printer.CStr();
            DesEncrypt(content, (char*)KEY_DES_KEY , fileName.c_str());
            delete doc;
        }
        else
        {
            doc->SaveFile(fileName.c_str());
            delete doc;
        }
	}
	else //进行保存
	{
        bool ret = false;
        TiXmlDocument* doc = new TiXmlDocument();
        if (true == VALUE_BOOL_IS_FILE_ENCRYPTED) {
            char* content = NULL;
            DesDecrypt(fileName.c_str(),  (char*)KEY_DES_KEY, content);
            
            const char* pRet = doc->Parse(content);
            if (! pRet)
            {
                delete doc;
                ret = false;
            }
            else
            {
                ret = true;
            }
        }
		else {
            ret = doc->LoadFile(fileName.c_str());
            if (!ret) {
                delete doc;
            }
        }
        if (ret == true) {
            TiXmlElement* root =  doc->RootElement();
            
            TiXmlElement* userName = root->FirstChildElement(KEY_USER_NAME);
            TiXmlText* userNameValue = (userName->FirstChild())->ToText();
            userNameValue->SetValue(m_userName.c_str());
            
            TiXmlElement* isRememberPassword = root->FirstChildElement(KEY_IS_REMEMBER_PASSWORD);
            TiXmlText* isRememberPasswordValue =(isRememberPassword->FirstChild())->ToText();
            isRememberPasswordValue->SetValue(m_isRememberPassword ? VALUE_BOOL_TRUE : VALUE_BOOL_FALSE);
            if (m_isRememberPassword) //如果有记住密码，则保存密码
            {
                TiXmlElement* passWord = root->FirstChildElement(KEY_PASSWORD);
                passWord->Clear();
                TiXmlText* passWordValue = new TiXmlText(m_passWord.c_str());
                passWord->LinkEndChild(passWordValue);
            }
            else
            {
                //do nothing
            }
            TiXmlElement* roles = root->FirstChildElement(KEY_ROLES);
            roles->Clear();
            for (int i = 0; i < m_roles.size(); i ++)
            {
                CRoleSetting* setting = m_roles[i];
                
                TiXmlElement* role = new TiXmlElement(KEY_ROLE);
                roles->LinkEndChild(role);
                
                TiXmlElement* roleName = new TiXmlElement(KEY_ROLE_NAME);
                role->LinkEndChild(roleName);
                TiXmlText* roleNameValue = new TiXmlText(setting->getRoleName().c_str());
                roleName->LinkEndChild(roleNameValue);
                
                TiXmlElement* isMusicOn = new TiXmlElement(KEY_IS_MUSIC_ON); //设置音乐
                role->LinkEndChild(isMusicOn);
                TiXmlText* isMusicOnValue = new TiXmlText(setting->getIsMusicOn() ?  VALUE_BOOL_TRUE : VALUE_BOOL_FALSE);
                isMusicOn->LinkEndChild(isMusicOnValue);
                
                TiXmlElement* isMusicEffectOn = new TiXmlElement(KEY_IS_MUSIC_EFFECT_ON); //设置音效
                role->LinkEndChild(isMusicEffectOn);
                TiXmlText* isMusicEffectOnValue = new TiXmlText(setting->getIsMusicEffectOn() ? VALUE_BOOL_TRUE : VALUE_BOOL_FALSE);
                isMusicEffectOn->LinkEndChild(isMusicEffectOnValue);
            }
        }
		
        
        //进行加密
        if (true == VALUE_BOOL_IS_FILE_ENCRYPTED)
        {
            TiXmlPrinter printer ;
            doc->Accept(&printer);
            const char* content = printer.CStr();
            DesEncrypt(content, (char*)KEY_DES_KEY , fileName.c_str());
            delete doc;
        }
        else
        {
            doc->SaveFile(fileName.c_str());
            delete doc;
        }
	}
    
	return true;
}

//根据角色名字获取CRoleSetting，如果不存在则返回NULL
CRoleSetting*  CUserSetting::getRoleItemByName(const char* roleName)
{
	CRoleSetting* ret = NULL;
	for (int i = 0; i < m_roles.size() && i < 4; i ++)
	{
		CRoleSetting* item = m_roles[i];
		if (item)
		{
			if (0 == strcmp(roleName, item->getRoleName().c_str()))
			{
				ret = item;
				break;
			}
		}
	}
    
	return ret;
}

//添加一个roleSetting
void  CUserSetting::addRoleItemByName(const char* roleName)
{
	if (getRoleItemByName(roleName) == NULL)
	{
		CRoleSetting* setting = new CRoleSetting();
		setting->setRoleName(roleName);
		vector<CRoleSetting*>::iterator it = m_roles.begin();
		m_roles.insert(it, setting);
        
		if (m_roles.size() > INT_MAX_ROLES)
		{
			m_roles.resize(INT_MAX_ROLES); //调整大小，上限是INT_MAX_ROLES个
		}
		saveSettings(); //保存改变的内容
	}
	else
	{
		//将该User的顺序置顶
		CRoleSetting* user= getRoleItemByName(roleName);
		vector<CRoleSetting*>tempVec ;
        
		for (int i = 0; i < m_roles.size() && i < INT_MAX_ROLES; i ++)
		{
			CRoleSetting* item = m_roles[i];
			if (item != user)
			{
				tempVec.push_back(item);
			}
		}
		tempVec.insert(tempVec.begin(), user);
		m_roles = tempVec;
		saveSettings();
	}
}

//删除一个userSetting
void  CUserSetting::deleteRoleItemByName(const char* roleName)
{
	int oriSize = m_roles.size();
	for (vector<CRoleSetting*>::iterator it = m_roles.begin(); it != m_roles.end();)
	{
		CRoleSetting* item = *it;
		if (strcmp(item->getRoleName().c_str(), roleName) == 0)
		{
			it = m_roles.erase(it);
		}
		else
		{
			it ++;
		}
	}
    
	int newSize = m_roles.size();
    
	if (oriSize != newSize) //检测内容有改变
	{
		saveSettings(); //保存改变的内容
	}
}


CGameSetting* CGameSetting::m_sharedInstance = NULL;

CGameSetting* CGameSetting::GetSharedInstance()
{
	if (m_sharedInstance == NULL)
	{
		m_sharedInstance = new CGameSetting();
		bool ret = m_sharedInstance->initSettings();
		if (ret == false)
		{
		    delete m_sharedInstance;
			m_sharedInstance = NULL;
		}
	}
	return m_sharedInstance;
}

void CGameSetting::DestroyInstance()
{
	if (m_sharedInstance)
	{
		delete m_sharedInstance;
		m_sharedInstance = NULL;
	}
}

CGameSetting::CGameSetting()
{
	
}

CGameSetting::~CGameSetting()
{
	for (int i = 0; i < m_users.size(); i ++)
	{
		delete m_users[i];
	}
}

bool CGameSetting::initSettings()
{
	string writePath = YHFileManger::sharedInstance()->getWriteablePath();
	writePath = writePath + FILE_USER_SETTING+"/";
	string gameSettingFileName = writePath + FILE_GAME_SETTING;
    bool bIsDirectory = false;
	{
        /*	string testFileName = writePath + "test.xml";
         string testFileNameCipher = writePath + "test.dat";
         string testFileNamePlain = writePath + "plain.xml";
         TiXmlDocument* doc = new TiXmlDocument(testFileName.c_str());
         doc->LoadFile( );
         TiXmlPrinter printer;
         doc->Accept(&printer);
         const char* fileContent = printer.CStr();
         DesEncrypt(fileContent, "palmworld", testFileNameCipher.c_str());
         delete doc;
         
         char * plainContent = NULL;
         DesDecrypt(testFileNameCipher.c_str(), "palmworld", plainContent);
         TiXmlDocument* docPlain  = new TiXmlDocument();
         docPlain->Parse(plainContent);
         
         bool ret = docPlain->SaveFile(testFileNamePlain.c_str());
         delete docPlain;
         delete[] plainContent;*/
	}
    
	if (! YHFileManger::sharedInstance()->fileExistsAtPath(gameSettingFileName.c_str(), &bIsDirectory)) //进行创建
	{
        YHFileManger::sharedInstance()->createDirectory(writePath.c_str(), "");
		TiXmlDocument* doc = new TiXmlDocument();
		TiXmlElement* root = new TiXmlElement("Root");
		doc->LinkEndChild(root);
		TiXmlElement* users = new TiXmlElement("Users");
		users->SetAttribute("number", 0);
		root->LinkEndChild(users);
		doc->SaveFile(gameSettingFileName.c_str());
		delete doc;
	}
    
	if (YHFileManger::sharedInstance()->fileExistsAtPath(gameSettingFileName.c_str(), &bIsDirectory))	//进行读取
	{
		TiXmlDocument* doc = new TiXmlDocument(gameSettingFileName.c_str());
		doc->LoadFile( /*TIXML_ENCODING_UTF8*/);
		TiXmlElement* rootElement = doc->RootElement();
		TiXmlElement* users = rootElement->FirstChildElement();
		int number = 0;
		users->Attribute("number", &number);
		TiXmlElement* userElement = users->FirstChildElement();
		for (int i = 0; i < number && i < 4 && userElement != NULL; i ++, userElement = userElement->NextSiblingElement())
		{
			TiXmlText* userName = (userElement->FirstChild())->ToText();
			string userfileName = writePath + userName->Value();
			CUserSetting* setting = new CUserSetting();
			setting->setUserName(userName->Value());
			bool ret = setting->initSettings(userfileName);
			if (ret)
			{
				m_users.push_back(setting);
			}
			else
			{
				delete setting;
			}
		}
		doc->SaveFile();
		delete doc;
	}
	return true;
}

bool CGameSetting::saveSettings()
{
	string writePath = YHFileManger::sharedInstance()->getWriteablePath();
	writePath = writePath + PATH_GAME_SETTING+"/";
	string gameSettingFileName = writePath + FILE_GAME_SETTING;
    
	TiXmlDocument* doc = new TiXmlDocument(gameSettingFileName.c_str());
	doc->LoadFile( /*TIXML_ENCODING_UTF8*/);
	TiXmlElement* rootElement = doc->RootElement();
	TiXmlElement* users = rootElement->FirstChildElement();
	int number = m_users.size();
    
	users->SetAttribute("number", number);
	users->Clear();
	for (int i = 0; i < number; i ++)
	{
		TiXmlElement* user = new TiXmlElement("User");
		users->LinkEndChild(user);
		TiXmlText* text = new TiXmlText(m_users[i]->getUserName().c_str());
		user->LinkEndChild(text);
	}
	doc->SaveFile();
	delete doc;
    
	return true;
}

CUserSetting* CGameSetting::getUserItemByName(const char* userName)
{
	CUserSetting* ret = NULL;
	for (int i = 0; i < m_users.size() && i < 4; i ++)
	{
		CUserSetting* item = m_users[i];
		if (item && item->getUserName().c_str() != NULL)
		{
			if (0 == strcmp(userName, item->getUserName().c_str()))
			{
				ret = item;
				break;
			}
		}
	}
    
	return ret;
}

void CGameSetting::addUserItemByName(const char* userName)
{
	if (getUserItemByName(userName) == NULL)
	{
		//分两步，第一步是建立用户个人文件夹,第二步是UsersInfo.xml
        
		//第一步
		string writePath = YHFileManger::sharedInstance()->getWriteablePath();
		writePath = writePath + PATH_GAME_SETTING+"/";
		string userPathName = writePath + userName;
		YHFileManger::sharedInstance()->createDirectory(userPathName.c_str(),"");//创建用户目录
        
		CUserSetting* setting = new CUserSetting();
		setting->setUserName(userName);
		bool ret = setting->initSettings(userPathName); //创建个人文件UserSetting.xml
		
		//第二步
		if (! ret)
		{
			delete setting;
		}
		else
		{
			vector<CUserSetting*>::iterator it = m_users.begin();
			m_users.insert(it, setting);
			if (m_users.size() > 4)
			{
				m_users.resize(4); //调整大小，上限是4个
			}
			saveSettings(); //保存改变的内容
		}
	}
	else
	{
		//将该User的顺序置顶
		CUserSetting* user= getUserItemByName(userName);
		vector<CUserSetting*>tempVec ;
        
		for (int i = 0; i < m_users.size() && i < 4; i ++)
		{
			CUserSetting* item = m_users[i];
			if (item != user)
			{
				tempVec.push_back(item);
			}
		}
		tempVec.insert(tempVec.begin(), user);
		m_users = tempVec;
		saveSettings();
	}
}

void CGameSetting::deleteUserItemByName(const char* userName)
{
	int oriSize = m_users.size();
	for (vector<CUserSetting*>::iterator it = m_users.begin(); it != m_users.end();)
	{
		CUserSetting* item = *it;
		if (strcmp(item->getUserName().c_str(), userName) == 0)
		{
			it = m_users.erase(it);
			//删除个人文件夹
			string writePath = YHFileManger::sharedInstance()->getWriteablePath();
			writePath = writePath + PATH_GAME_SETTING+"/";
			string userPathName = writePath + userName;
			YHFileManger::sharedInstance()->removeDirectory(userPathName.c_str());
		}
		else
		{
			it ++;
		}
	}
    
	int newSize = m_users.size();
    
	if (oriSize != newSize) //检测内容有改变
	{
		saveSettings(); //保存改变的内容
	}
}